package org.zachary.imitation.raft;

import com.google.protobuf.Message;
import org.zachary.imitation.raft.option.NodeOptions;
import org.zachary.imitation.raft.rpc.RpcRequestClosure;
import org.zachary.imitation.raft.rpc.RpcRequests;

/**
 * 对集群中服务器的抽象，一个节点就表示集群中的一台服务器
 *
 * Created by guozhaokun on 2024/8/30 11:15.
 */
public interface Node extends Lifecycle<NodeOptions> {

	/** 获取节点的状态 */
	State getState();

	/** 获取节点的唯一标识*/
	NodeId getNodeId();

	/** 获取节点所属的 groupId（集群 ID） */
	String getGroupId();

	/** 获取当前节点在当前任期的 Leader 节点 */
	PeerId getLeader();

	/** 获取节点当前所处于的任期 */
	long getTerm();

	/** 处理预投票（索票）请求，当前节点接收到另一个节点发送的预投票（索票）的请求时，就会通过这个方法来处理，这个方法的参数就是集群中的候选者节点发送过来的 RPC 预投票（索票）请求 */
	RpcRequests.RequestVoteResponse handlePreVoteRequest(final RpcRequests.RequestVoteRequest request);

	/** 处理正式投票（索票）请求，当前节点接收到另一个节点发送的正式投票（索票）的请求时，就会通过这个方法来处理，这个方法的参数就是集群中的候选者节点发送过来的 RPC 正式投票（索票）请求 */
	RpcRequests.RequestVoteResponse handleRequestVoteRequest(final RpcRequests.RequestVoteRequest request);

	/** 当前节点接收到 Leader 发送过来的消息时，不管消息是日志复制还是心跳消息，还是探针消息，都会调用该方法进行处理。其实 Leader 发送的日志复制消息，以及心跳消息探针消息，使用的都是同一个 RPC 请求 */
	Message handleAppendEntriesRequest(final RpcRequests.AppendEntriesRequest request, final RpcRequestClosure done);
}
